package org.hh.netty.server;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.SneakyThrows;
import org.hh.netty.utils.SysUtils;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 服务器处理类
 */
@ChannelHandler.Sharable
public class TeacherServerHandler extends ChannelInboundHandlerAdapter {

    //客户端Channel集合
    private static ChannelGroup clientChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    /**
     * 上线
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        clientChannels.add(channel);

        String sendMsg = "客户[" + channel.remoteAddress() + "]上线\n";
        clientChannels.forEach(clientChannel ->{
            if(clientChannel != channel) {
                clientChannel.writeAndFlush(sendMsg);
            }
            else {
                clientChannel.writeAndFlush("欢迎您上线\n");
            }
        });
    }

    /**
     * 下线
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        if (clientChannels.contains(channel)) {
            clientChannels.remove(channel);

            String sendMsg = "客户[" + channel.remoteAddress() + "]异常下线\n";
            System.out.print(sendMsg);
            clientChannels.forEach(clientChannel -> clientChannel.writeAndFlush(sendMsg));
        }
    }

    /**
     * 收到消息
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Channel channel = ctx.channel();

        //设置默认信息
        AtomicReference<String> sendMsg = new AtomicReference<>("客户[" + channel.remoteAddress() + "]消息: " + msg + "\n");
        //如果是退出指令，则改为XXX下线通知
        if (msg instanceof String && msg.equals("quit")) {
            clientChannels.remove(channel);
            channel.close();
            sendMsg.set("客户[" + channel.remoteAddress() + "]下线\n");
            System.out.print(sendMsg.get());
        }
        clientChannels.forEach(clientChannel -> {
            if (clientChannel != channel) {
                clientChannel.writeAndFlush(sendMsg.get());
            }
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        Channel channel = ctx.channel();
        clientChannels.remove(channel);

        String msg = cause.getMessage();
        String sendMsg = "客户[" + channel.remoteAddress() + "]异常: " + msg + "\n";
        System.out.print(sendMsg);
        clientChannels.forEach(clientChannel -> clientChannel.writeAndFlush(sendMsg));
    }

    /**
     * 发送屏幕到客户端
     */
    @SneakyThrows
    public void sendScreen() {
        BufferedImage bufferedImage = SysUtils.getScreeImage();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(byteArrayOutputStream);
        encoder.encode(bufferedImage);
        clientChannels.forEach(clientChannel -> {
            clientChannel.writeAndFlush(byteArrayOutputStream.toByteArray());
        });
    }

    /**
     * 发送全屏或取消全屏信息
     * @param msg
     */
    public void fullMsg(String msg){
        clientChannels.forEach(clientChannel -> {
            clientChannel.writeAndFlush(msg);
        });
    }
}
